/*
 * SortableTableModel.java
 *
 * Created on August 29, 2007, 11:02 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.afaker.rss.gui.table;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collections;
import java.util.Vector;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

/**
 *
 * @author bruce
 */
public class SortableTableModel extends AbstractTableModel implements TableModelListener{
    private TableModel tableModel;
    private  int sortCol = -1;
    private  boolean sortAsc = true;
    private int [] rowMap;
    private int editingRow;
    /** Creates a new instance of SortableTableModel */
    public SortableTableModel(TableModel model) {
        this.tableModel = model;
        tableModel.addTableModelListener(this);
    }
    
    public boolean isCellEditable(int row,int col) {
        return tableModel.isCellEditable(row,col);
    }
    
    public int getRowCount() {
        return  tableModel.getRowCount();
    }
    
    public int getColumnCount() {
        return tableModel.getColumnCount();
    }
    
    public Class getColumnClass(int columnIndex) {
        return tableModel.getColumnClass(columnIndex);
    }
    
    public String getColumnName(int column) {
        if(sortCol == column)
            return tableModel.getColumnName(column) + (sortAsc ? ">>" : "<<");
        return tableModel.getColumnName(column);
    }
    
    public Object getValueAt(int row, int col) {
        return tableModel.getValueAt(getOriginalRow(row),col);
    }
    
    public void setValueAt(Object value,int row,int col) {
        editingRow = row;
        tableModel.setValueAt(value,getOriginalRow(row),col);
    }
    
    public int getOriginalRow(int sortedRow) {
        if(rowMap.length == 0 || rowMap == null)
            return 0;
        return rowMap[sortedRow];
    }
    
    public void tableChanged(TableModelEvent e) {
        /**if e == null that means the whole table changed*/
        if(e == null) {
            rowMap = new int[tableModel.getRowCount()];
            for (int i = 0; i < rowMap.length; i++) {
                rowMap[i] = i;
            }
            sortAsc = true;
            sortCol = -1;
            fireTableChanged(null);
        } else{
            if(e.getType() != e.ALL_COLUMNS && e.getFirstRow() == e.getLastRow() && e.getType() == e.UPDATE) {
                fireTableCellUpdated(editingRow,0);
            }
        }
        
    }
    
    public class VectorWithRow {
        public Vector v;
        public int row;
        public VectorWithRow(Vector v,int row) {
            this.v = v;
            this.row =row;
        }
    }
    
    public class ColumnListener extends MouseAdapter {
        private JTable table;
        /** Creates a new instance of ColumnListener */
        public ColumnListener(JTable table) {
            this.table = table;
        }
        
        public void mouseClicked(MouseEvent e) {
            if(rowMap.length != tableModel.getRowCount())
                rowMap = new int[tableModel.getRowCount()];
            TableColumnModel colModel = table.getColumnModel();
            int columnModelIndex = colModel.getColumnIndexAtX(e.getX());
            int modelIndex = colModel.getColumn(columnModelIndex).getModelIndex();
            if (modelIndex < 0)
                return;
            if (sortCol == modelIndex)
                sortAsc = !sortAsc;
            else
                sortCol = modelIndex;
            for (int i = 0; i < getColumnCount() ; i++) {
                TableColumn column = colModel.getColumn(i);
                column.setHeaderValue(getColumnName(column.getModelIndex()));
            }
            table.getTableHeader().repaint();
            Vector data = new Vector();
            Vector v;
            VectorWithRow vwr = null;
            for (int i = 0; i < tableModel.getRowCount(); i++) {
                v = new Vector();
                for (int j = 0; j < tableModel.getColumnCount(); j++) {
                    v.add(tableModel.getValueAt(i,j));
                }
                vwr = new VectorWithRow(v,i);
                data.addElement(vwr);
                
            }
            Collections.sort(data, new FeedDataComparator(modelIndex, sortAsc));
            for (int i = 0; i < rowMap.length; i++) {
                rowMap[i] = ((VectorWithRow) data.elementAt(i)).row;
            }
            table.tableChanged(
                    new TableModelEvent(SortableTableModel.this));
            table.repaint();
        }
    }
    
}
